package org.Yiran.timetale_re.entity.rune;

import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.ThrowableItemProjectile;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.HitResult;
import net.minecraftforge.network.NetworkHooks;
import org.Yiran.timetale_re.entity.EntityRegister;
import org.Yiran.timetale_re.item.ItemsRegister;
import org.Yiran.timetale_re.item.rune.base.RuneAbility;
import org.Yiran.timetale_re.item.rune.base.RuneItem;
import org.Yiran.timetale_re.item.rune.base.RuneRegistry;
import org.Yiran.timetale_re.item.rune.type.throwable.base.ThrowableRune;
import org.jetbrains.annotations.NotNull;

import java.util.UUID;

/**
 * 可投掷符文实体类
 * <p>
 * 该类表示一个可投掷的符文物品实体，继承自ThrowableItemProjectile。
 * 具有以下功能：
 * 1. 作为投掷物在世界中飞行
 * 2. 击中目标或方块时触发符文效果
 * 3. 生成破碎粒子效果
 * 4. 防火特性以防止被火焰点燃
 * </p>
 */
public class ThrowableRuneEntity extends ThrowableItemProjectile {
    
    // ============================== 实体数据访问器 ==============================
    
    private static final EntityDataAccessor<String> RUNE_TYPE = SynchedEntityData.defineId(ThrowableRuneEntity.class, EntityDataSerializers.STRING);
    
    // ============================== 实例变量 ==============================
    
    private UUID ownerUUID;      // 所有者UUID
    private ItemStack runeStack; // 符文物品堆栈

    // ============================== 构造方法 ==============================
    
    /**
     * 构造函数 - 用于实体注册
     * 
     * @param entityType 实体类型
     * @param level 世界对象
     */
    public ThrowableRuneEntity(EntityType<? extends ThrowableRuneEntity> entityType, Level level) {
        super(entityType, level);
    }

    /**
     * 构造函数 - 创建可投掷符文实体
     * 
     * @param level 世界对象
     * @param player 投掷玩家
     * @param runeStack 符文物品堆栈
     */
    public ThrowableRuneEntity(Level level, Player player, ItemStack runeStack) {
        super(EntityRegister.THROWABLE_RUNE.get(), level);
        this.setOwner(player);
        this.ownerUUID = player.getUUID();
        this.runeStack = runeStack.copy();
        this.entityData.set(RUNE_TYPE, RuneItem.getRuneType(runeStack));
    }

    // ============================== 数据同步方法 ==============================
    
    /**
     * 定义同步数据
     * <p>
     * 初始化实体的同步数据，包括符文类型
     * </p>
     */
    @Override
    protected void defineSynchedData() {
        super.defineSynchedData();
        this.entityData.define(RUNE_TYPE, RuneItem.BLANK);
    }

    // ============================== 物品相关方法 ==============================
    
    /**
     * 获取默认物品
     * <p>
     * 创建包含符文类型信息的 ItemStack 用于渲染
     * </p>
     * 
     * @return 默认物品
     */
    @Override
    protected @NotNull Item getDefaultItem() {
        // 创建包含符文类型信息的 ItemStack
        ItemStack stack = new ItemStack(ItemsRegister.RUNE.get());
        RuneItem.setRuneType(stack, this.entityData.get(RUNE_TYPE));
        return stack.getItem();
    }

    // ============================== 实体更新方法 ==============================
    
    /**
     * 实体更新方法
     * <p>
     * 每tick调用一次，处理实体逻辑
     * </p>
     */
    @Override
    public void tick() {
        super.tick();

        // 超时保护
        if (!this.level().isClientSide() && this.tickCount > 1800) {
            this.discard();
        }
    }

    // ============================== 防火特性方法 ==============================
    
    /**
     * 添加防火特性 - 使实体无法被火焰点燃
     * 
     * @return true表示实体对火焰免疫
     */
    @Override
    public boolean fireImmune() {
        return true;
    }

    /**
     * 添加防火特性 - 防止实体着火
     * 
     * @return false表示实体不会着火
     */
    @Override
    public boolean isOnFire() {
        return false;
    }

    // ============================== 击中处理方法 ==============================
    
    /**
     * 击中处理方法
     * <p>
     * 当实体击中目标或方块时调用，执行符文效果并生成粒子效果
     * </p>
     * 
     * @param result 击中结果
     */
    @Override
    protected void onHit(@NotNull HitResult result) {
        super.onHit(result);

        if (!this.level().isClientSide) {
            // 播放音效
            this.level().playSound(null, this.getX(), this.getY(), this.getZ(),
                    SoundEvents.GLASS_BREAK, SoundSource.PLAYERS, 1.0F, 1.0F);

            // 执行符文效果
            executeRuneEffect(result);

            spawnRuneBreakParticles();

            // 销毁实体
            this.discard();
        }
    }

    // ============================== 粒子效果方法 ==============================
    
    /**
     * 生成符文破碎粒子效果
     * <p>
     * 在客户端生成符文破碎时的粒子效果
     * </p>
     */
    private void spawnRuneBreakParticles() {
        if (this.level().isClientSide && this.runeStack != null && !this.runeStack.isEmpty()) {
            // 生成符文物品的粒子效果
            for (int i = 0; i < 8; i++) {
                double offsetX = (this.level().random.nextFloat() - 0.5) * 0.5;
                double offsetY = (this.level().random.nextFloat() - 0.5) * 0.5;
                double offsetZ = (this.level().random.nextFloat() - 0.5) * 0.5;

                this.level().addParticle(
                        new net.minecraft.core.particles.ItemParticleOption(
                                net.minecraft.core.particles.ParticleTypes.ITEM,
                                this.runeStack
                        ),
                        this.getX() + offsetX,
                        this.getY() + offsetY,
                        this.getZ() + offsetZ,
                        (this.level().random.nextFloat() - 0.5) * 0.1,
                        (this.level().random.nextFloat() - 0.5) * 0.1,
                        (this.level().random.nextFloat() - 0.5) * 0.1
                );
            }
        }
    }

    // ============================== 符文效果方法 ==============================
    
    /**
     * 执行符文效果
     * <p>
     * 根据符文类型执行对应的可投掷符文效果
     * </p>
     * 
     * @param result 击中结果
     */
    private void executeRuneEffect(HitResult result) {
        String runeType = this.entityData.get(RUNE_TYPE);
        RuneAbility ability = RuneRegistry.getRuneAbility(runeType);

        if (ability instanceof ThrowableRune throwableRune && this.getOwner() instanceof Player player) {
            // 使用保存的符文物品堆栈来执行效果
            if (runeStack != null) {
                // 执行符文效果
                try {
                    throwableRune.executeRuneEffect(runeStack, this.level(), player, result.getLocation());
                } catch (Exception e) {
                    // 忽略异常，防止崩溃
                }
            }
        }
    }

    // ============================== 网络同步方法 ==============================
    
    /**
     * 获取实体生成数据包
     * 
     * @return 实体生成数据包
     */
    @Override
    public Packet<ClientGamePacketListener> getAddEntityPacket() {
        return NetworkHooks.getEntitySpawningPacket(this);
    }

    // ============================== 数据同步更新方法 ==============================
    
    /**
     * 当同步数据更新时调用
     * <p>
     * 当符文类型更新时，确保实体能正确渲染
     * </p>
     * 
     * @param key 更新的数据访问器
     */
    @Override
    public void onSyncedDataUpdated(@NotNull EntityDataAccessor<?> key) {
        super.onSyncedDataUpdated(key);
        if (RUNE_TYPE.equals(key)) {
            // 当符文类型更新时，确保实体能正确渲染
            this.runeStack = createRuneStackFromType(this.entityData.get(RUNE_TYPE));
        }
    }

    // ============================== 辅助方法 ==============================
    
    /**
     * 根据符文类型创建符文物品堆栈
     * 
     * @param runeType 符文类型
     * @return 符文物品堆栈
     */
    private ItemStack createRuneStackFromType(String runeType) {
        ItemStack stack = new ItemStack(ItemsRegister.RUNE.get());
        RuneItem.setRuneType(stack, runeType);
        return stack;
    }

    // ============================== Getter和Setter方法 ==============================
    
    public String getRuneType() {
        return this.entityData.get(RUNE_TYPE);
    }

    public void setRuneType(String type) {
        this.entityData.set(RUNE_TYPE, type);
    }

    public UUID getOwnerUUID() {
        return this.ownerUUID;
    }

    public void setOwnerUUID(UUID ownerUUID) {
        this.ownerUUID = ownerUUID;
    }

    // 提供获取符文物品堆栈的方法
    public ItemStack getRuneStack() {
        return runeStack != null ? runeStack : ItemStack.EMPTY;
    }
}